package cn.com.header.zbpk.account.service.impl;

import cn.com.header.core.IPage;
import cn.com.header.core.ISort;
import cn.com.header.core.helper.Beans;
import cn.com.header.core.sort.Sorter;
import cn.com.header.core.support.web.ResultCode;
import cn.com.header.zbpk.account.entity.Role;
import cn.com.header.zbpk.account.entity.User;
import cn.com.header.zbpk.account.mapper.IRoleMapper;
import cn.com.header.zbpk.account.mapper.IUserMapper;
import cn.com.header.zbpk.account.mapper.IUserRoleMapper;
import cn.com.header.zbpk.account.model.RoleExtend;
import cn.com.header.zbpk.account.model.RoleType;
import cn.com.header.zbpk.account.model.UserRole;
import cn.com.header.zbpk.account.service.IRoleAuthorityService;
import cn.com.header.zbpk.account.service.IRoleService;
import cn.com.header.zbpk.exception.ServiceException;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.beans.IntrospectionException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author luohaidian
 * @date 2017-11-17
 * @time 09:19
 */
@Service
public class RoleServiceImpl implements IRoleService {

    @Autowired
    private IRoleMapper iRoleMapper;

    @Autowired
    private IUserRoleMapper iUserRoleMapper;

    @Autowired
    private IUserMapper iUserMapper;

    @Autowired
    private IRoleAuthorityService iRoleAuthorityService;

    @Override
    public List<Role> queryBy(Long schoolId) {
        Set<String> fields = Sets.newHashSet("id", "name", "type");
        Set<ISort> sortSet = Sets.newHashSet(new Sorter("create_time", true));
        Role role = new Role();
        role.setSchoolId(schoolId);
        List<Role> roleList = iRoleMapper.loads(role, fields, sortSet, null);
        // roleList = roleList.stream().filter(r -> !r.getType().equals(RoleType.SCHOOL_ADMIN)).collect(Collectors.toList());
        return roleList;
    }

    @Override
    public List<? extends Role> customLoads(Role role, Set<String> fields, Set<ISort> sortSet, IPage page) {
        List<Role> roleList = iRoleMapper.loads(role, fields, sortSet, page);
        List<RoleExtend> roleExtendList = Lists.newLinkedList();
        for (Role roleVo : roleList){
            RoleExtend roleExtend = new RoleExtend();
            roleExtend.setId(roleVo.getId());
            roleExtend.setName(roleVo.getName());
            roleExtend.setCreateTime(roleVo.getCreateTime());
            roleExtend.setRemark(roleVo.getRemark());
            // TODO PS:代码有待优化
            List<String> nameList = iRoleMapper.customLoads(roleVo.getId(), Sets.newHashSet("U.name"));
            roleExtend.setOweUserCount(nameList.size());
            roleExtend.setOweUserNameList(nameList.stream().collect(Collectors.toList()));
            roleExtendList.add(roleExtend);
        }
        return roleExtendList;
    }

    @Override
    public int loadCount(Role role) {
        return iRoleMapper.loadCount(role);
    }

    @Override
    public boolean saveOrUpdate(Role role) {
        if (Strings.isNullOrEmpty(role.getName())){
            throw new ServiceException(ResultCode.PARAM_ERROR, "角色名称不能为空！！！");
        }
        if (!NAME_PATTERN.matcher(role.getName()).matches()){
            throw new ServiceException(ResultCode.PARAM_ERROR, "角色名称应为2至10个中文！！！");
        }
        if (Objects.isNull(role.getId())){
            Role checkRole = new Role();
            checkRole.setName(role.getName());
            checkRole.setSchoolId(role.getSchoolId());
            if (iRoleMapper.loadCount(checkRole) > 0){
                throw new ServiceException(ResultCode.DUPLICATION, "该学校已经存在[" + role.getName() + "]的角色名称！！！");
            }
            role.setType(RoleType.TEACHER);
            role.setCreateTime(LocalDateTime.now());
            boolean inserted = iRoleMapper.insert(role) > 0;
            if (inserted) {
                iRoleAuthorityService.genearteRoleAuthority(role);
            }
            return  inserted;
        }
        Optional<Role> optional = this.loadByPK(role.getId(), null);
        if (!optional.isPresent()){
            throw new ServiceException(ResultCode.PARAM_ERROR, "角色ID[ "+ role.getId() +"]有误！！！");
        }
        Role roleVo = optional.get();
        if (!Objects.equals(roleVo.getName(), role.getName())){
            Role checkRole = new Role();
            checkRole.setName(role.getName());
            checkRole.setSchoolId(role.getSchoolId());
            if (iRoleMapper.loadCount(checkRole) > 0){
                throw new ServiceException(ResultCode.DUPLICATION, "该学校已经存在[" + role.getName() + "]的角色名称！！！");
            }
        }
        return iRoleMapper.update(role) > 0;
    }

    @Override
    public List<Role> queryRoleByUserId(Long userId) {
        List<UserRole> userRoleList = iUserRoleMapper.loadByUserId(Sets.newHashSet("role_id"), userId);
        List<Long> roleIdList = userRoleList.stream().map(x -> x.getRoleId()).collect(Collectors.toList());
        List<Role> roleList = iRoleMapper.queryRole(Sets.newHashSet("id", "name", "type"), roleIdList);
        return roleList;
    }

    @Override
    public boolean insertBatch(List<Role> roleList) {
        return iRoleMapper.insertBatch(roleList) > 0;
    }

    @Override
    public synchronized boolean delete(Long roleId) {
        Role role = this.loadByPK(roleId, Sets.newHashSet("type")).get();
        RoleType roleType = role.getType();
        if(RoleType.SCHOOL_ADMIN.equals(roleType) || RoleType.SCHOOL_MASTER.equals(roleType) || RoleType.STUDENT.equals(roleType)){
            throw new ServiceException(ResultCode.FAIL,"该角色不能删除！！！");
        }
        if(iUserRoleMapper.loadCount(new UserRole(null, roleId)) > 0){
            throw new ServiceException(ResultCode.FAIL,"该角色下存在用户，不能进行删除！！！");
        }
        return iRoleMapper.delete(roleId) > 0;
    }

    @Override
    public Map<String, Object> queryRoleUser(Long roleId) {
        List<UserRole> roleList = iUserRoleMapper.loadByRoleId(Sets.newHashSet("user_id"), roleId);
        Set<Long> userIdSet = roleList.stream().map(x->x.getUserId()).collect(Collectors.toSet());
        Map<String,Object> resultMap = Maps.newHashMapWithExpectedSize(userIdSet.size());
        List<User> userList = Lists.newArrayList();
        if (Objects.nonNull(userIdSet) && !userIdSet.isEmpty()){
            userList = iUserMapper.loadByPKs(userIdSet, Sets.newHashSet("id","name"));
        }
        resultMap.put("userList",userList);
        return resultMap;
    }

    @Override
    public List<String> queryRoleTypeByUserId(Long userId) {
        List<UserRole> userRoles = iUserRoleMapper.loadByUserId(Sets.newHashSet("role_id"), userId);
        List<Long> roleIds = userRoles.stream().map(x -> x.getRoleId()).collect(Collectors.toList());
        List<Role> roleList = iRoleMapper.queryRole(Sets.newHashSet("type"), roleIds);
        List<String> roleTypeList = roleList.stream().map(x -> x.getType().toString()).collect(Collectors.toList());
        return roleTypeList;
    }

    @Override
    public Optional<Role> loadByPK(Long id, Set<String> fields) {
        Role role = new Role(id);
        List<Role> roleList = iRoleMapper.loads(role, fields, null, null);
        if (Objects.isNull(roleList) || roleList.isEmpty()){
            return Optional.empty();
        }
        return Optional.of(roleList.get(0));
    }

    @Override
    public Map<String, Object> queryMapByRoleId(Long roleId) {
        Role role = loadByPK(roleId, null).get();
        Map<String, Object> dataMap = Maps.newHashMapWithExpectedSize(6);
        try {
            Beans.transformBeanToMap(role, dataMap);
        } catch (IntrospectionException | ReflectiveOperationException e) {
            throw new ServiceException("将Role对象转为Map出错！！！");
        }
        return dataMap;
    }

}
